package com.taoding.springbootbase.base.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.taoding.springbootbase.base.entity.User;
import com.taoding.springbootbase.base.model.UserSession;
import com.taoding.springbootbase.base.service.SessionService;
import com.taoding.springbootbase.util.CommonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author wuwentan
 * @date 2018/8/17
 */
@Service
public class SessionServiceImpl implements SessionService {

    @Autowired
    StringRedisTemplate redisTemplate;

    @Value("${system.session-times}")
    long sessionTimes;

    @Override
    public boolean checkIsValid(String key) {
        return StringUtils.isNotBlank(key) && redisTemplate.hasKey(key);
    }

    @Override
    public UserSession newUserSession(User user) {
        //组装Session并保存
        UserSession session = getUserSessionByUserId(user.getId());
        if(Objects.isNull(session)){
            session = new UserSession();
            String sessionId = CommonUtils.getUUID();
            session.setSessionId(sessionId);

            //设置用户实体属性
            session.setUserId(user.getId());
            session.setUsername(user.getUsername());
            session.setName(user.getName());
            session.setFlag(user.getFlag());
            session.setIsAdmin(user.getIsAdmin());
            session.setCorpId(user.getCorpId());
            session.setRoleCodeList(user.getRoleCodeList());
        }
        saveUserSession(session);
        return session;
    }

    @Override
    public void saveUserSession(UserSession userSession) {
        String sessionId = userSession.getSessionId();
        String userId = userSession.getUserId();

        //构建一个以sessionId为key的string类型的数据
        redisTemplate.boundValueOps(sessionId).set(JSON.toJSONString(userSession));

        //设置以sessionId为key的数据过期时间
        if(-1 != sessionTimes){
            redisTemplate.expire(sessionId, sessionTimes, TimeUnit.MINUTES);
        }

        //构建一个以userId为key的string类型的数据，以便查询，否则不知道userId和session数据的对应关系
        redisTemplate.boundValueOps(userId).set(sessionId);

        //设置以userId为key的数据过期时间
        if(-1 != sessionTimes){
            redisTemplate.expire(userId, sessionTimes, TimeUnit.MINUTES);
        }
    }

    @Override
    public void refreshUserSession(User user) {
        UserSession session = getUserSessionByUserId(user.getId());
        if(!Objects.isNull(session)){
            //设置用户实体属性
            session.setUsername(user.getUsername());
            session.setName(user.getName());
            session.setFlag(user.getFlag());
            session.setIsAdmin(user.getIsAdmin());
            session.setCorpId(user.getCorpId());
            session.setRoleCodeList(user.getRoleCodeList());
            //更新用户session信息
            saveUserSession(session);
        }
    }

    @Override
    public UserSession getUserSessionById(String sessionId) {
        if (StringUtils.isNotBlank(sessionId)) {
            String sessionStr = redisTemplate.boundValueOps(sessionId).get();
            return JSON.parseObject(sessionStr, UserSession.class);
        }
        return null;
    }

    @Override
    public UserSession getUserSessionByUserId(String userId) {
        if (StringUtils.isNotBlank(userId)) {
            String sessionId = redisTemplate.boundValueOps(userId).get();
            if(StringUtils.isNotBlank(sessionId)){
                String sessionStr = redisTemplate.boundValueOps(sessionId).get();
                return JSON.parseObject(sessionStr, new TypeReference<UserSession>() { });
            }
        }
        return null;
    }

    @Override
    public void removeUserSession(String sessionId) {
        UserSession session = this.getUserSessionById(sessionId);
        if (session != null && StringUtils.isNotBlank(session.getSessionId()) && redisTemplate.hasKey(session.getSessionId())) {
            redisTemplate.delete(session.getSessionId());
            redisTemplate.delete(session.getUserId());
            UserSession.remove();
        }
    }
}